package org.jarx.android.reader;

import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ExpandableListActivity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ExpandableListView;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.ResourceCursorTreeAdapter;
import android.widget.TextView;

public class TagListActivity extends ExpandableListActivity {

    private static final String TAG = "TagListActivity";
    private static final int DIALOG_MARK_ALL_AS_READ = 1;

    private final Handler handler = new Handler();
    private TagsAdapter tagsAdapter;
    private int groupLastExpandedPos;
    private TextView allLabelView;

    private BroadcastReceiver refreshReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            TagListActivity.this.initListAdapter();
        }
    };

    private BroadcastReceiver startReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context c, Intent intent) {
            String action = intent.getAction();
            boolean busy = intent.getBooleanExtra("busy", true);
            CharSequence text = null;
            if (action.equals(ReaderService.ACTION_START_SYNC_RESULT)) {
                if (busy) {
                    text = getText(R.string.msg_service_busy);
                } else {
                    text = getText(R.string.msg_sync_started);
                }
            }
            if (text != null) {
                ActivityHelper.showToast(c, text);
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        IntentFilter filter = new IntentFilter();
        filter.addAction(ReaderService.ACTION_SYNC_SUBS_FINISHED);
        filter.addAction(ReaderService.ACTION_UNREAD_MODIFIED);
        registerReceiver(this.refreshReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(ReaderService.ACTION_START_SYNC_RESULT);
        registerReceiver(this.startReceiver, filter);

        setContentView(R.layout.tag_list);

        ExpandableListView listView = getExpandableListView();
        listView.setGroupIndicator(null);

        LayoutInflater inflater = (LayoutInflater) getSystemService(
            Context.LAYOUT_INFLATER_SERVICE);
        View headerView = inflater.inflate(R.layout.tag_list_row, null);
        this.allLabelView = (TextView) headerView.findViewById(R.id.label);
        listView.addHeaderView(headerView, "", true);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView p, View  v, int pos, long id) {
                if (pos == 0) {
                    ActivityHelper.startItemActivity(TagListActivity.this);
                }
            }
        });

        ActivityHelper.bindTitle(this);
        initListAdapter();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (this.groupLastExpandedPos > 0) {
            getExpandableListView().expandGroup(this.groupLastExpandedPos);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.tag_list, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_reload:
            sendBroadcast(new Intent(ReaderService.ACTION_START_SYNC));
            return true;
        case R.id.menu_mark_as_read:
            showDialog(DIALOG_MARK_ALL_AS_READ);
            return true;
        case R.id.menu_prefs:
            startActivityForResult(new Intent(this, PrefActivity.class),
                ActivityHelper.REQUEST_PREFS);
            return true;
        }
        return false;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == ActivityHelper.REQUEST_PREFS) {
            initListAdapter();
        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case DIALOG_MARK_ALL_AS_READ:
            return new AlertDialog.Builder(this)
                .setTitle(R.string.txt_reads)
                .setMessage(R.string.msg_confirm_mark_as_read_all)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        progressMarkAllAsRead();
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    }
                }).create();
        }
        return null;
    }

    @Override
    public void onGroupCollapse(int pos) {
        this.groupLastExpandedPos = 0;
        Tag.FilterCursor tagCsr = (Tag.FilterCursor) this.tagsAdapter.getGroup(pos);
        int type = tagCsr.getType();
        if (type == Tag.TYPE_TAG_STARRED || type == Tag.TYPE_TAG_LABEL) {
            ActivityHelper.startItemActivityByTagUid(this, tagCsr.getUid());
        }
    }

    @Override
    public void onGroupExpand(int pos) {
        Tag.FilterCursor tagCsr = (Tag.FilterCursor) this.tagsAdapter.getGroup(pos);
        int type = tagCsr.getType();
        if (type == Tag.TYPE_TAG_STARRED || type == Tag.TYPE_TAG_LABEL) {
            ActivityHelper.startItemActivityByTagUid(this, tagCsr.getUid());
        } else {
            this.groupLastExpandedPos = pos;
        }
    }

    @Override
    public boolean onChildClick(ExpandableListView parent, View v,
            int groupPosition, int childPosition, long id) {
        Object t = v.getTag();
        if (t == null) {
            ActivityHelper.startItemActivity(this);
        } else if (t instanceof Long) {
            ActivityHelper.startItemActivityBySubId(this, (Long) t);
        } else {
            ActivityHelper.startItemActivityByTagUid(this, String.valueOf(t));
        }
        return true;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("groupLastExpandedPos", this.groupLastExpandedPos);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        this.groupLastExpandedPos = savedInstanceState.getInt("groupLastExpandedPos");
    }

    public synchronized void initListAdapter() {
        Context c = getApplicationContext();
        this.allLabelView.setText(ActivityHelper.toLabelWithUnread(
            getText(R.string.txt_all), Prefs.getUnreadCount(c)));

        Cursor csr = new Tag.FilterCursor(managedQuery(
            Tag.CONTENT_URI, null, null, null, null));
        if (this.tagsAdapter == null) {
            this.tagsAdapter = new TagsAdapter(this, csr);
            setListAdapter(this.tagsAdapter);
        } else {
            this.tagsAdapter.changeCursor(csr);
        }
    }

    private void progressMarkAllAsRead() {
        final Handler handler = new Handler();
        final long time = System.currentTimeMillis();
        final Context c = getApplicationContext();
        final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setIndeterminate(true);
        dialog.setMessage(getText(R.string.msg_mark_as_read_running));
        dialog.show();
        new Thread() {
            public void run() {
                ReaderManager rman = ReaderManager.newInstance(c);
                try {
                    rman.syncMarkAllAsRead(time);
                } catch (IOException e) {
                    ActivityHelper.showToast(c, e);
                } catch (ReaderException e) {
                    ActivityHelper.showToast(c, e);
                }
                handler.post(new Runnable() {
                    public void run() {
                        dialog.dismiss();
                    }
                });
            }
        }.start();
    }

    private class TagsAdapter extends ResourceCursorTreeAdapter {

        private TagsAdapter(Context c, Cursor csr) {
            super(c, csr, R.layout.tag_list_row, R.layout.tag_list_row);
        }

        @Override
        public Cursor getChildrenCursor(Cursor groupCsr) {
            Tag.FilterCursor tagCsr = (Tag.FilterCursor) groupCsr;
            if (tagCsr.getType() == Tag.TYPE_FOLDER) {
                String tagUid = tagCsr.getUid();
                Query q = ReaderManager.getSubQueryByTagUid(tagUid,
                    Prefs.isViewUnreadOnly(TagListActivity.this));
                Cursor csr = q.managedQuery(TagListActivity.this);
                if (csr.getCount() > 1) {
                    return new TagSubFilterCursor(csr, tagUid);
                } else {
                    return new Subscription.FilterCursor(csr);
                }
            } else {
                return null;
            }
        }

        @Override
        public void bindGroupView(View v, Context c, Cursor csr,
                boolean isExpanded) {
            Tag.FilterCursor tagCsr = (Tag.FilterCursor) csr;
            Tag tag = tagCsr.getTag();

            ImageView iconView = (ImageView) v.findViewById(R.id.icon);
            TextView labelView = (TextView) v.findViewById(R.id.label);

            labelView.setText(ActivityHelper.toLabelWithUnread(tag,
                TagListActivity.this));

            switch (tag.getType()) {
            case Tag.TYPE_TAG_STARRED:
                iconView.setImageResource(R.drawable.star);
                break;
            case Tag.TYPE_TAG_LABEL:
                iconView.setImageResource(R.drawable.tag);
                break;
            case Tag.TYPE_FOLDER:
                if (isExpanded) {
                    iconView.setImageResource(R.drawable.folder_open);
                } else {
                    iconView.setImageResource(R.drawable.folder_close);
                }
                break;
            }

            v.setTag(tag.getId());
        }

        @Override
        public void bindChildView(View v, Context c, Cursor csr,
                boolean isLastChild) {
            Subscription.FilterCursor subCsr = (Subscription.FilterCursor) csr;
            Subscription sub = subCsr.getSubscription();

            TextView labelView = (TextView) v.findViewById(R.id.label);
            ImageView iconView = (ImageView) v.findViewById(R.id.icon);

            if (sub instanceof TagUidSub) {
                iconView.setVisibility(View.GONE);
                labelView.setPadding(20, 4, 0, 0);
                labelView.setText(getText(R.string.txt_folder_items));

                v.setTag(((TagUidSub) sub).getTagUid());
            } else {
                iconView.setVisibility(View.VISIBLE);
                iconView.setPadding(20, 4, 0, 0);
                Bitmap icon = sub.getIcon(TagListActivity.this);
                if (icon == null) {
                    iconView.setImageResource(R.drawable.feed_default);
                } else {
                    iconView.setImageBitmap(icon);
                }
                labelView.setPadding(8, 0, 0, 0);
                labelView.setText(ActivityHelper.toLabelWithUnread(sub));

                v.setTag(sub.getId());
            }
        }
    }

    private static class TagSubFilterCursor extends Subscription.FilterCursor {

        private final int csrCount;
        private final Subscription firstSub;
        private int pos;

        private TagSubFilterCursor(Cursor csr, String tagUid) {
            super(csr);
            this.csrCount = csr.getCount();
            this.firstSub = new TagUidSub(tagUid);
        }

        public int getCount() {
            return this.csrCount + 1;
        }

        public boolean isFirst() {
            return (this.pos == 0);
        }

        public boolean isLast() {
            return (this.pos == this.csrCount);
        }

        public boolean move(int offset) {
            this.pos += offset;
            if (this.pos == 0) {
                return true;
            }
            return super.move(offset);
        }

        public boolean moveToFirst() {
            this.pos = 0;
            return true;
        }

        public boolean moveToLast() {
            this.pos = this.csrCount;
            return super.moveToLast();
        }

        public boolean moveToNext() {
            this.pos++;
            return super.moveToPosition(this.pos - 1);
        }

        public boolean moveToPrevious() {
            this.pos--;
            if (this.pos == 0) {
                return true;
            }
            return super.moveToPosition(this.pos - 1);
        }

        public boolean moveToPosition(int position) {
            this.pos = position;
            if (this.pos == 0) {
                return true;
            }
            return super.moveToPosition(this.pos - 1);
        }

        public int getPosition() {
            return this.pos;
        }

        public Subscription getSubscription() {
            if (this.pos == 0) {
                return this.firstSub;
            }
            return super.getSubscription();
        }
    }

    public static class TagUidSub extends Subscription {

        private String tagUid;

        public TagUidSub() {
            super();
        }

        public TagUidSub(String tagUid) {
            super();
            this.tagUid = tagUid;
        }

        public String getTagUid() {
            return this.tagUid;
        }

        public void setTagUid(String tagUid) {
            this.tagUid = tagUid;
        }
    }
}
